package com.cskaoyan.javase.oop2._2polymorphic._2advantage;

import javafx.animation.Animation;
import javafx.geometry.VPos;

/**
 * 多态的优缺点,顺便讲一下: 多态的使用场景,以及向下转型
 * 引例:
 * 科学家要收集动物的叫声去研究
 * 先要收集猫，狗两种动物的叫声研究。
 * 随后又扩展到其它动物，最后又需要研究人类。
 *
 * 多态在实际开发中的应用,多在方法的形参中写父类类型,然后传入不同的子类对象
 * 调用同名子类重写的方法,从而产生不同的行为,这依然是多态.
 *
 * 多态的优点:
 *      1.要实现多态必须要继承，而继承提高了代码复用率，提升了程序的可维护性。（继承保证）
 *      2.有了多态后，用父类引用指向不同子类对象，只需要调用同名方法，就能自动根据不同子类对象，得出不同的行为。
 *      这大幅度简化了代码，提升了程序的扩展性。（多态保证）
 *
 * 多态的缺点:
 *      由于多态中，使用父类引用指向子类对象，父类引用限制了子类对象的功能，这意味着：
 *      子类独有的成员是无法使用父类引用访问的。
 *
 * 当然多态的这个缺点是可以改变的,只需要将父类引用重新转换为子类引用就可以了
 * 这个将 父类引用 --> 子类引用的过程属于
 * 引用数据类型的强制类型转换(向下转向)
 *
 *
 * @since 09:40
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // collectCatVoice(new Cat());
        // collectCatVoice(new Dog());

        collectAnimalVoice(new Person());
        collectAnimalVoice(new Cat());
        collectAnimalVoice(new Dog());
        collectAnimalVoice(new Pig());
    }

    // 收集研究猫的叫声
    /*public static void collectCatVoice(Cat c) {
        // 抓一只猫过来,让它叫
        c.shout();
        // 收集研究它的叫声
    }*/

    // 收集研究所有动物的叫声
    public static void collectAnimalVoice(Animal a) {
        /*
            如果是人类,研究它的叫声
            需要先调用addMoney()方法
            但是这里的引用a能够调用子类独有方法吗?
            显然是不能的,父类引用指向子类对象,父类引用限制了子类对象的访问范围,无法访问子类独有成员
            需要做强转
            因为方法可能传入非Person的Animal子类对象
            所以我们需要一个语法来完成强转的判断,避免程序出现类型转换异常
            这种语法就是Java中的instanceof关键字
         */
        if (a instanceof Person) {
            Person p = (Person) a;
            p.addMoney();
        }
        // 抓一只动物过来,让它叫
        a.shout();
        // 收集研究它的叫声
    }
}

// 动物的父类
class Animal {
    void shout() {
        System.out.println("动物叫~");
    }
}

class Cat extends Animal {
    @Override
    void shout() {
        System.out.println("喵喵喵~");
    }
}

class Dog extends Animal {
    @Override
    void shout() {
        System.out.println("旺旺旺~");
    }
}

class Pig extends Animal {
    @Override
    void shout() {
        System.out.println("小猪佩奇的叫声~~");
    }
}

class Person extends Animal {
    /*
        人类比较特殊
        要想人类配合研究,要花钱
        所以人类有一个特殊的行为: 加钱
        加钱之前,才叫

        这个方法在父类中没有,它属于子类独有的方法
     */
    public void addMoney() {
        System.out.println("给钱就好办事,想咋叫咋叫!!");
    }


    @Override
    void shout() {
        System.out.println("嘤嘤嘤嘤~~");
    }
}